package deanandjames.sprite;

import deanandjames.image.ImageLoader;

public class Avatar extends Sprite {
	private static double DURATION = 0.5;
	private static final int FALLING = 2;
	private static final int MAX_UP_STEPS = 8;
	private static final int NOT_JUMPING = 0;
	private static final int RISING = 1;
	private final BrickManager brickMan;
	private boolean isFacingRight;
	private boolean isStill;
	private final int moveSize;
	private final int period;
	private int upCount;
	private int vertMoveMode;
	private final int vertStep;
	private int xWorld;
	private int yWorld;

	public Avatar(int width, int height, int brickMoveSize, BrickManager brickManager, ImageLoader imageLoader, int period) {
		super(width / 2, height / 2, width, height, imageLoader, "runningRight");
		moveSize = brickMoveSize;
		brickMan = brickManager;
		this.period = period;
		setStep(0, 0);
		isFacingRight = true;
		isStill = true;
		locy = brickMan.findFloor(locationX + getWidth() / 2) - getHeight();
		xWorld = locationX;
		yWorld = locy;
		vertMoveMode = NOT_JUMPING;
		vertStep = brickMan.getBrickHeight() / 2;
		upCount = 0;
	}

	public boolean isMovingLeft() {
		return !isFacingRight && !isStill;
	}

	public boolean isMovingRight() {
		return isFacingRight && !isStill;
	}

	public void jump() {
		if (vertMoveMode == NOT_JUMPING) {
			vertMoveMode = RISING;
			upCount = 0;
			if (isStill) {
				if (isFacingRight) {
					setImage("jumpRight");
				} else {
					setImage("jumpLeft");
				}
			}
		}
	}

	public void moveLeft() {
		setImage("runningLeft");
		loopImage(period, DURATION);
		isFacingRight = false;
		isStill = false;
	}

	public void moveRight() {
		setImage("runningRight");
		loopImage(period, DURATION);
		isFacingRight = true;
		isStill = false;
	}

	public void stayStill() {
		stopLooping();
		isStill = true;
	}

	@Override
	public void updateSprite() {
		if (!isStill) {
			if (isFacingRight) {
				xWorld += moveSize;
			} else {
				xWorld -= moveSize;
			}
			if (vertMoveMode == NOT_JUMPING) {
				checkIfFalling();
			}
		}
		if (vertMoveMode == RISING) {
			updateRising();
		} else if (vertMoveMode == FALLING) {
			updateFalling();
		}
		super.updateSprite();
	}

	public boolean willHitBrick() {
		if (isStill) {
			return false;
		}
		int xTest;
		if (isFacingRight) {
			xTest = xWorld + moveSize;
		} else {
			xTest = xWorld - moveSize;
		}
		final int xMid = xTest + getWidth() / 2;
		final int yMid = yWorld + (int) (getHeight() * 0.8);
		return brickMan.insideBrick(xMid, yMid);
	}

	private void checkIfFalling() {
		final int yTrans = brickMan.checkBrickTop(xWorld + getWidth() / 2, yWorld + getHeight() + vertStep, vertStep);
		if (yTrans != 0) {
			vertMoveMode = FALLING;
		}
	}

	private void finishJumping() {
		vertMoveMode = NOT_JUMPING;
		upCount = 0;
		if (isStill) {
			if (isFacingRight) {
				setImage("runningRight");
			} else {
				setImage("runningLeft");
			}
		}
	}

	private void updateFalling() {
		final int yTrans = brickMan.checkBrickTop(xWorld + getWidth() / 2, yWorld + getHeight() + vertStep, vertStep);
		if (yTrans == 0) {
			finishJumping();
		} else {
			translate(0, yTrans);
			yWorld += yTrans;
		}
	}

	private void updateRising() {
		if (upCount == MAX_UP_STEPS) {
			vertMoveMode = FALLING;
			upCount = 0;
		} else {
			int yTrans = brickMan.checkBrickBase(xWorld + getWidth() / 2, yWorld - vertStep, vertStep);
			if (yTrans == 0) {
				vertMoveMode = FALLING;
				upCount = 0;
			} else {
				translate(0, -yTrans);
				yWorld -= yTrans;
				upCount++;
			}
		}
	}
}
